import { Component, Prop, Ref, Watch } from 'vue-facing-decorator'
import Render from '@/render/Render'
import toNative from '@/utils/toNative'
import type { JSX } from 'vue/jsx-runtime'
import { nextTick, watch, type ComponentPublicInstance } from 'vue'

export interface TreeCardDto {
    title: string
    titleRight?: JSX.Element
    id: number
    content: string | number | JSX.Element
    children?: TreeCardDto[]
    parentId?: number
    visible?: boolean
    active?: boolean
    rect?: DOMRect
}

interface PositionRefDto {
    el: HTMLElement
    data: DOMRect
}

@Component
export class TreeRelationCard extends Render {
    @Prop() treeData!: TreeCardDto[]

    treeRef = [] as HTMLElement[]

    refPositionData = {
        parent: {} as PositionRefDto,
        son: [] as PositionRefDto[]
    }

    treeList = [] as TreeCardDto[][]

    positionData = [] as DOMRect[][]

    defaultActive = 0

    @Watch('treeData', { immediate: true })
    handleWatch() {
        this.initTreeData(this.treeData)
        this.treeList = this.setTreeList()
        this.setVisible()
    }

    // 初始化树形结构，为每个节点设置id和parentId
    initTreeData(list: TreeCardDto[], parentId: number = 0) {
        list.forEach((i, index) => {
            if (!i?.id) {
                i.id = parentId * 10 + (parentId === 0 ? 1 : parentId) + index
                i.parentId = parentId
            }
            if (i?.children) {
                this.initTreeData(i.children, i.id)
            }
        })
    }

    // 设置树形结构，将原本的children结构改造成多维数组，方便渲染
    setTreeList() {
        const res = [] as TreeCardDto[][]
        function setList(list: TreeCardDto[], index: number = 0) {
            list.forEach((i) => {
                if (!Array.isArray(res[index])) {
                    res[index] = []
                }
                res[index].push(i)
                if (i?.children) {
                    setList(i.children, index + 1)
                }
            })
        }
        setList(this.treeData)
        return res
    }

    // 设置可见，第一组默认全部可见，第二组根据defaultVisible设置,其他组取前一组的第0个，判断parendId是不是当前组的id的相等
    setVisible() {
        for (let i = 0; i < this.treeList.length; i++) {
            this.treeList[i].forEach((k, index) => {
                k.active = i === 0 ? index === this.defaultActive : index === 0
            })
            if (i === 0) {
                this.treeList[i].forEach((k) => {
                    k.visible = true
                })
            } else {
                this.treeList[i].forEach((k) => {
                    const idx = this.treeList[i - 1].findIndex((i) => i.active)
                    k.visible = k.parentId === this.treeList[i - 1][idx].id
                })
            }
        }
    }

    setRefData(el: HTMLElement, index: number, sonIndex: number) {
        if (!el || this.positionData.length) return
        nextTick(() => {
            if (!Array.isArray(this.positionData[index])) {
                this.positionData[index] = []
            }
            this.positionData[index][sonIndex] = el.getBoundingClientRect()
            this.treeList[index][sonIndex].rect = el.getBoundingClientRect()
        })

        console.log(111, this.treeList)
        console.log(222, this.positionData)
    }
    setClass(i: TreeCardDto, index: number, sonIndex: number) {
        // console.log(555, i, index, sonIndex)
        if (i.visible) {
            return `tree-card-${i.id}`
        }
        return ''
    }

    updatePosition(list: TreeCardDto[]) {
        nextTick(() => {
            list.forEach((i) => {
                if (i.visible) {
                    const el = document.querySelector(`.tree-card-${i.id}`)
                    el && (i.rect = el.getBoundingClientRect())
                }
                if (i.children && i.children.length) {
                    this.updatePosition(i.children)
                }
            })
        })
    }

    onCardClick(item: TreeCardDto, index: number) {
        this.treeList[index].forEach((k) => {
            k.active = false
        })
        item.active = true
        if (index === 0) {
            this.defaultActive = item.id
        }
        for (let i = index + 1; i < this.treeList.length; i++) {
            this.treeList[i].forEach((k) => {
                const idx = this.treeList[i - 1].findIndex((k) => k.active)
                k.visible =
                    k.parentId === (i === index + 1 ? item.id : this.treeList[i - 1][idx].id)
                k.active = false
            })
            const idx = this.treeList[i].findIndex((k) => k.visible)
            if (idx !== -1) {
                this.treeList[i][idx].active = true
            }
        }
        this.treeList.forEach((i) => {
            this.updatePosition(i)
        })
    }

    renderCard(i: TreeCardDto, index: number, sonIndex: number) {
        const parent = this.treeList[index - 1]?.find((k) => k.id === i.parentId)
        const gapTop = 20
        return (
            <div class="relative">
                <div
                    ref={(el) => this.setRefData(el as HTMLElement, index, sonIndex)}
                    class={`my-10px ${this.setClass(i, index, sonIndex)}`}
                    onClick={() => this.onCardClick(i, index)}
                >
                    <div
                        class={`min-w-300px flex-shrink-0 rounded-lg border-1 border-solid  overflow-hidden ${i.active ? '!border-blue-100' : 'border-blue-300'}`}
                    >
                        <div
                            class={`flex justify-between items-center px-20px pt-16px pb-12px ${i.active ? '!bg-blue-300' : 'border-blue-300'}`}
                        >
                            <div>{i.title}</div>
                            <div>{i.titleRight}</div>
                        </div>
                        <div class="px-16px py-12px">
                            t: {i.rect?.top} h: {i.rect?.height} y: {i.rect?.y}
                            {i.content}
                        </div>
                    </div>
                </div>
                {i.children ? (
                    i.children.map((k) => {
                        const parentTop = i.rect?.top as number
                        const sonTop = k.rect?.top as number
                        return (
                            k.visible && (
                                <div
                                    class="absolute h-full -right-21px"
                                    style={{ top: parentTop > sonTop ? '3px' : `${gapTop}px` }}
                                >
                                    {parentTop === sonTop ? (
                                        <div
                                            class={`w-21px border-t-3px border-t-solid ${i.active && k.active ? 'border-t-blue-100 relative z-10' : 'border-t-blue-300'}`}
                                        ></div>
                                    ) : parentTop < sonTop ? (
                                        <div
                                            style={{ height: `${sonTop - parentTop - gapTop}px` }}
                                            class={`w-21px border-t-3px border-t-solid ${i.active && k.active ? 'border-t-blue-100 border-r-blue-100 relative z-10' : 'border-t-blue-300'} border-r-3px border-r-solid rounded-tr-15px`}
                                        ></div>
                                    ) : parentTop > sonTop ? (
                                        <div
                                            class={`w-21px h-20px border-b-3px border-b-solid ${i.active && k.active ? 'border-b-blue-100 border-r-blue-100 relative z-10' : 'border-t-blue-300'} border-r-3px border-r-solid rounded-br-15px`}
                                        ></div>
                                    ) : (
                                        <></>
                                    )}
                                </div>
                            )
                        )
                    })
                ) : (
                    <></>
                )}
                {i.parentId && i.parentId !== 0 ? (
                    this.renderSonBorder(parent as TreeCardDto, i, gapTop)
                ) : (
                    <></>
                )}
            </div>
        )
    }

    renderSonBorder(parent: TreeCardDto, son: TreeCardDto, gapTop: number) {
        const parentTop = parent?.rect?.top as number
        const sonTop = son?.rect?.top as number
        return (
            <div
                class="absolute h-full -left-18px top-0"
                style={{
                    top:
                        parentTop >= sonTop
                            ? `${gapTop}px`
                            : -(Math.abs(parentTop - sonTop) - gapTop * 2) + 'px',
                    height:
                        parentTop === sonTop
                            ? Math.abs(parentTop - sonTop) + 'px'
                            : parentTop < sonTop
                                ? Math.abs(parentTop - sonTop) - (gapTop) + 'px'
                                : Math.abs(parentTop - sonTop - (gapTop / 2) ) + 'px'
                }}
            >
                {parentTop === sonTop ? (
                    <div
                        class={`w-18px h-full border-b-3px border-b-solid ${son.active ? 'border-b-blue-100 relative z-10' : 'border-b-blue-300'}`}
                    ></div>
                ) : parentTop < sonTop ? (
                    <div
                        class={`w-18px h-full border-b-3px border-b-solid ${son.active ? 'border-b-blue-100 border-l-blue-100 relative z-10' : 'border-b-blue-300'} border-l-3px border-l-solid rounded-bl-15px`}
                    ></div>
                ) : parentTop > sonTop ? (
                    <div
                        class={`w-18px h-full border-t-3px border-b-solid ${son.active ? 'border-t-blue-100 border-l-blue-100 relative z-10' : 'border-b-blue-300'} border-l-3px border-l-solid rounded-tl-15px`}
                    ></div>
                ) : (
                    <></>
                )}
            </div>
        )
    }

    render() {
        return (
            <>
                <div class="flex gap-36px">
                    {this.treeList.map((item, index) => {
                        return (
                            <>
                                <div class="flex flex-col ">
                                    {item.map((i, sonIndex) => {
                                        return (
                                            i.visible && (
                                                <div class="flex">
                                                    <div class="flex-1">
                                                        {this.renderCard(i, index, sonIndex)}
                                                    </div>
                                                </div>
                                            )
                                        )
                                    })}
                                </div>
                            </>
                        )
                    })}
                </div>
            </>
        )
    }
}

export default toNative<{ treeData: TreeCardDto[] }, {}>(TreeRelationCard)
